package com.waypolice.common.ftp;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/**
 * 描述:
 *
 * @author zyp
 * @description FTP抽象父类
 * @create 2018-08-22 9:38
 */
public abstract class FTPBase {

    private static Logger logger = LoggerFactory.getLogger(FTPBase.class);

    public FTPClient ftpClient = null;

    /**
     * 初始化ftp
     */
    public abstract boolean initFTPClient();

    /**
     * @author:zyp
     * @description 上传的文件地址
     * @date: 2018/8/22 11:07
     * @return
     *  fileName:上传到ftp服务器上的文件名称
     *  upload_path:源文件所在的本地路径
     *  pathname:上传到文件的文件地址
     */
    public boolean uploadFile( String fileName,String pathname, String upload_path) {
        logger.info("上传文件的名字:"+fileName+"；上传的文件路径："+pathname+"；上传的文件源地址:"+upload_path);
        boolean isConnect = initFTPClient();
        boolean flag = false;
        if(!isConnect){
            logger.info("----FTP连接失败，终止上传逻辑----");
            return flag;
        }
        InputStream inputStream = null;
        try {
            logger.info("----开始上传文件----");
            inputStream = new FileInputStream(new File(upload_path));
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            CreateDirecroty(pathname);
            boolean isUpload = ftpClient.storeFile(fileName, inputStream);
            inputStream.close();
            ftpClient.logout();
            if(isUpload){
                flag = true;
                logger.info("----上传成功----");
            }else{
                logger.info("----上传失败----");
            }
        } catch (Exception e) {
            logger.error("----程序异常----上传失败----");
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /**
     * @author:zyp
     * @description 以文件流的形式进行上传
     * @date: 2018/8/22 11:06
     * @return
     * fileName:上传入ftp服务器上的文件名称
     * inputStream:需要上传的文件流
     * pathname:上传到文件的文件地址
     */
    public boolean uploadFile(String fileName,String pathname,InputStream inputStream) {
        logger.info("上传文件的名字:"+fileName+"; 上传的文件路径："+pathname);
        boolean isConnect = initFTPClient();
        boolean flag = false;
        if(!isConnect){
            logger.info("----FTP连接失败，终止上传逻辑----");
            return flag;
        }
        try {
            logger.info("----开始上传文件----");
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            CreateDirecroty(pathname);
            boolean result = ftpClient.storeFile(fileName, inputStream);
            inputStream.close();
            ftpClient.logout();
            if(result){
                flag = true;
                logger.info("----上传文件成功----");
            }else{
                logger.info("----上传文件失败----");
            }
        } catch (Exception e) {
            logger.error("----程序异常----上传文件失败----");
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /**
     * @author:zyp
     * @description 下载文件
     * @date: 2018/8/22 11:19
     * @return
     * fileName:下载的文件的文件名
     * pathname:现在服务器的文件地址
     * down_path:下载后放的地址
     */
    public boolean downloadFile(String fileName,String pathname,String down_path) {
        logger.info("下载文件的名字:"+fileName+"；下载的文件路径："+pathname+"；下载后放入本地的地址"+down_path);
        boolean isConnect = initFTPClient();
        boolean flag = false;
        if(!isConnect){
            logger.info("----FTP连接失败，终止下载逻辑----");
            return flag;
        }
        OutputStream os = null;
        try {
            logger.info("----开始下载文件----");
            // 切换FTP目录
            boolean isChange = ftpClient.changeWorkingDirectory(pathname);
            if(!isChange){
                logger.info("----下载文件失败！无此文件地址----");
            }else{
                FTPFile[] ftpFiles = ftpClient.listFiles();
                for (FTPFile file : ftpFiles) {
                    if (fileName.equalsIgnoreCase(file.getName())) {
                        File localFile = new File(down_path + "/" + file.getName());
                        os = new FileOutputStream(localFile);
                        boolean falg = ftpClient.retrieveFile(file.getName(), os);
                        os.close();
                        flag = true;
                        logger.info("----下载文件成功----");
                    }
                }
                ftpClient.logout();
            }
        } catch (Exception e) {
            logger.error("----下载文件失败----");
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (!flag){
            logger.info("----下载文件失败----");
        }
        return flag;
    }

    /**
     * @author:zyp
     * @description 删除文件
     * @date: 2018/8/22 9:52
     * @return
     * fileName:文件名
     */
    public boolean deleteFile(String fileName,String pathname) {
        logger.info("删除文件的名字:"+fileName+"；删除的文件ftp路径："+pathname);
        boolean isConnect = initFTPClient();
        boolean flag = false;
        if(!isConnect){
            logger.info("----FTP连接失败，终止删除逻辑----");
            return flag;
        }
        try {
            logger.info("----开始删除文件----");
            // 切换FTP目录
            ftpClient.changeWorkingDirectory(pathname);
            ftpClient.dele(fileName);
            ftpClient.logout();
            flag = true;
            logger.info("----删除文件成功----");
        } catch (Exception e) {
            logger.error("----删除文件失败----");
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /**
     * 创建多层目录文件夹，如果有ftp服务器已存在该文件夹，则不创建，如果无，则创建
     * @param remote 文件夹地址
     * @return
     * @throws IOException
     */
    private boolean CreateDirecroty(String remote) throws IOException {
        boolean success = true;
        String directory = remote + "/";
        // 如果远程目录不存在，则递归创建远程服务器目录
        if (!directory.equalsIgnoreCase("/")
                && !changeWorkingDirectory(new String(directory))) {
            int start = 0;
            int end = 0;
            if (directory.startsWith("/")) {
                start = 1;
            } else {
                start = 0;
            }
            end = directory.indexOf("/", start);
            StringBuilder path = new StringBuilder();
            while (true) {
                String subDirectory = new String(remote.substring(start, end)
                        .getBytes("GBK"), "iso-8859-1");
                path.append(subDirectory);
                if (!existFile(path.toString())) {
                    if (makeDirectory(subDirectory)) {
                        changeWorkingDirectory(subDirectory);
                    } else {
                        logger.info("创建目录[" + subDirectory + "]失败");
                        changeWorkingDirectory(subDirectory);
                    }
                } else {
                    changeWorkingDirectory(subDirectory);
                }
                start = end + 1;
                end = directory.indexOf("/", start);
                // 检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return success;
    }

    /**
     * 判断ftp服务器文件是否存在
     * @param path 文件名
     * @return
     * @throws IOException
     */
    private boolean existFile(String path) throws IOException {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        if (ftpFileArr.length > 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * 创建文件夹名字
     * @param dir 文件夹名
     * @return
     */
    private boolean makeDirectory(String dir) {
        boolean flag = true;
        try {
            flag = ftpClient.makeDirectory(dir);
            if (flag) {
                logger.info("创建文件夹" + dir + " 成功！");
            } else {
                logger.info("创建文件夹" + dir + " 失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 进入ftp服务器文件夹
     * @param directory 文件夹
     * @return
     */
    private boolean changeWorkingDirectory(String directory) {
        boolean flag = true;
        try {
            flag = ftpClient.changeWorkingDirectory(directory);
            if (flag) {
                logger.info("进入文件夹" + directory + " 成功！");
            } else {
                logger.info("进入文件夹" + directory + " 失败！开始创建文件夹");
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return flag;
    }

}